"""
文件系统工具模块
提供项目目录管理、文件读写等工具函数
"""
import os
import json
import shutil
from pathlib import Path
from typing import Optional, Dict, Any
from loguru import logger


def ensure_dir(path: str) -> Path:
    """
    确保目录存在，不存在则创建
    
    Args:
        path: 目录路径
        
    Returns:
        Path对象
    """
    dir_path = Path(path)
    dir_path.mkdir(parents=True, exist_ok=True)
    return dir_path


def get_project_dir(project_name: str, base_path: str = "./projects") -> Path:
    """
    获取项目目录路径
    
    Args:
        project_name: 项目名称
        base_path: 基础路径
        
    Returns:
        项目目录Path对象
    """
    return ensure_dir(os.path.join(base_path, project_name))


def save_json(data: Dict[str, Any], filepath: str) -> None:
    """
    保存JSON数据到文件
    
    Args:
        data: 要保存的数据字典
        filepath: 文件路径
    """
    import time
    start_time = time.time()
    
    ensure_dir(os.path.dirname(filepath))
    with open(filepath, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2, default=str)
    
    file_size = os.path.getsize(filepath)
    elapsed = time.time() - start_time
    
    logger.debug(f"已保存JSON到: {filepath}")
    logger.debug(f"  大小: {file_size} 字节 ({file_size / 1024:.2f} KB), 耗时: {elapsed:.3f}秒")
    
    # 记录性能日志
    logger.bind(duration=elapsed).trace(f"文件写入: {filepath} | 大小={file_size}字节")


def load_json(filepath: str) -> Optional[Dict[str, Any]]:
    """
    从文件加载JSON数据
    
    Args:
        filepath: 文件路径
        
    Returns:
        JSON数据字典，文件不存在返回None
    """
    if not os.path.exists(filepath):
        logger.warning(f"JSON文件不存在: {filepath}")
        return None
    
    import time
    start_time = time.time()
    
    try:
        file_size = os.path.getsize(filepath)
        with open(filepath, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        elapsed = time.time() - start_time
        logger.debug(f"已加载JSON: {filepath}")
        logger.debug(f"  大小: {file_size} 字节 ({file_size / 1024:.2f} KB), 耗时: {elapsed:.3f}秒")
        
        # 记录性能日志
        logger.bind(duration=elapsed).trace(f"文件读取: {filepath} | 大小={file_size}字节")
        
        return data
    except Exception as e:
        logger.error(f"加载JSON失败 {filepath}: {e}")
        logger.exception("文件加载异常详情:")
        return None


def save_text(content: str, filepath: str) -> None:
    """
    保存文本内容到文件
    
    Args:
        content: 文本内容
        filepath: 文件路径
    """
    import time
    start_time = time.time()
    
    ensure_dir(os.path.dirname(filepath))
    with open(filepath, 'w', encoding='utf-8') as f:
        f.write(content)
    
    file_size = os.path.getsize(filepath)
    elapsed = time.time() - start_time
    
    logger.debug(f"已保存文本到: {filepath}")
    logger.debug(f"  大小: {file_size} 字节 ({file_size / 1024:.2f} KB), 内容长度: {len(content)} 字符, 耗时: {elapsed:.3f}秒")
    
    # 记录性能日志
    logger.bind(duration=elapsed).trace(f"文件写入: {filepath} | 大小={file_size}字节")


def load_text(filepath: str) -> Optional[str]:
    """
    从文件加载文本内容
    
    Args:
        filepath: 文件路径
        
    Returns:
        文本内容，文件不存在返回None
    """
    if not os.path.exists(filepath):
        logger.warning(f"文本文件不存在: {filepath}")
        return None
    
    import time
    start_time = time.time()
    
    try:
        file_size = os.path.getsize(filepath)
        with open(filepath, 'r', encoding='utf-8') as f:
            content = f.read()
        
        elapsed = time.time() - start_time
        logger.debug(f"已加载文本: {filepath}")
        logger.debug(f"  大小: {file_size} 字节 ({file_size / 1024:.2f} KB), 内容长度: {len(content)} 字符, 耗时: {elapsed:.3f}秒")
        
        # 记录性能日志
        logger.bind(duration=elapsed).trace(f"文件读取: {filepath} | 大小={file_size}字节")
        
        return content
    except Exception as e:
        logger.error(f"加载文本失败 {filepath}: {e}")
        logger.exception("文件加载异常详情:")
        return None


def copy_file(src: str, dst: str) -> bool:
    """
    复制文件
    
    Args:
        src: 源文件路径
        dst: 目标文件路径
        
    Returns:
        是否成功
    """
    import time
    start_time = time.time()
    
    try:
        ensure_dir(os.path.dirname(dst))
        src_size = os.path.getsize(src)
        shutil.copy2(src, dst)
        
        elapsed = time.time() - start_time
        logger.debug(f"已复制文件: {src} -> {dst}")
        logger.debug(f"  大小: {src_size} 字节 ({src_size / 1024:.2f} KB), 耗时: {elapsed:.3f}秒")
        
        # 记录性能日志
        logger.bind(duration=elapsed).trace(f"文件复制: {src} -> {dst} | 大小={src_size}字节")
        
        return True
    except Exception as e:
        logger.error(f"复制文件失败 {src} -> {dst}: {e}")
        logger.exception("文件复制异常详情:")
        return False


def generate_id(prefix: str = "") -> str:
    """
    生成唯一ID（简单实现，使用时间戳+随机数）
    
    Args:
        prefix: ID前缀
        
    Returns:
        唯一ID字符串
    """
    import time
    import random
    timestamp = int(time.time() * 1000)
    rand = random.randint(1000, 9999)
    return f"{prefix}{timestamp}_{rand}" if prefix else f"{timestamp}_{rand}"


def create_multi_role_run_dir(project_name: str, run_type: str, base_path: str = "./projects") -> Path:
    """
    为多角色协作运行创建目录
    
    Args:
        project_name: 项目名称
        run_type: 运行类型（如：outline_generation, episode_generation, novel_generation）
        base_path: 项目基础路径
        
    Returns:
        运行目录的Path对象
    """
    from datetime import datetime
    
    # 创建时间戳（格式：YYYYMMDD_HHMMSS）
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    
    # 构建目录路径：projects/{project_name}/multi_role_runs/{timestamp}_{run_type}
    project_dir = Path(base_path) / project_name
    runs_dir = project_dir / "multi_role_runs"
    run_dir = runs_dir / f"{timestamp}_{run_type}"
    
    # 创建目录
    run_dir.mkdir(parents=True, exist_ok=True)
    
    logger.info(f"创建多角色运行目录: {run_dir}")
    return run_dir


def save_role_output(
    run_dir: Path,
    role_name: str,
    step_number: int,
    output_data: dict,
    input_data: dict = None,
    metadata: dict = None
) -> None:
    """
    保存角色输出到文件
    
    Args:
        run_dir: 运行目录
        role_name: 角色名称
        step_number: 步骤编号（1-based）
        output_data: 输出数据字典
        input_data: 输入数据字典（可选）
        metadata: 元数据（如：耗时、Token使用等）
    """
    import time
    from datetime import datetime
    
    start_time = time.time()
    
    # 文件名前缀
    prefix = f"{step_number:02d}_{role_name}"
    
    # 准备完整的数据结构
    full_data = {
        "role": role_name,
        "step": step_number,
        "timestamp": datetime.now().isoformat(),
        "output": output_data
    }
    
    if input_data:
        full_data["input"] = input_data
    
    if metadata:
        full_data["metadata"] = metadata
    
    # 保存JSON格式
    json_file = run_dir / f"{prefix}_output.json"
    save_json(full_data, str(json_file))
    
    # 保存Markdown格式（便于阅读）
    md_file = run_dir / f"{prefix}_output.md"
    md_content = _format_role_output_markdown(role_name, step_number, output_data, input_data, metadata)
    save_text(md_content, str(md_file))
    
    elapsed = time.time() - start_time
    logger.debug(f"已保存角色输出: {role_name}, 文件: {prefix}_output.*")
    logger.bind(duration=elapsed).trace(f"保存角色输出: {prefix}")


def _format_role_output_markdown(
    role_name: str,
    step_number: int,
    output_data: dict,
    input_data: dict = None,
    metadata: dict = None
) -> str:
    """
    将角色输出格式化为Markdown
    
    Args:
        role_name: 角色名称
        step_number: 步骤编号
        output_data: 输出数据
        input_data: 输入数据（可选）
        metadata: 元数据（可选）
        
    Returns:
        Markdown格式字符串
    """
    from datetime import datetime
    import json
    
    lines = []
    
    # 标题
    role_names = {
        "planner": "计划者（Planner）",
        "outliner": "大纲编写者（Outliner）",
        "character_designer": "角色设计师（Character Designer）",
        "scriptwriter": "剧本编写者（Scriptwriter）",
        "editor": "编辑者（Editor）",
        "outline_expander": "大纲扩展者（Outline Expander）"
    }
    
    role_display = role_names.get(role_name, role_name)
    lines.append(f"# 步骤 {step_number}: {role_display}")
    lines.append(f"\n**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    lines.append(f"**角色**: {role_name}\n")
    
    # 元数据
    if metadata:
        lines.append("## 执行信息\n")
        for key, value in metadata.items():
            lines.append(f"- **{key}**: {value}")
        lines.append("")
    
    # 输入信息（简化）
    if input_data:
        lines.append("## 输入信息\n")
        # 只显示关键信息，避免太长
        for key in ["project", "task", "target_episodes"]:
            if key in input_data:
                lines.append(f"- **{key}**: {input_data[key]}")
        lines.append("")
    
    # 输出内容
    lines.append("## 输出内容\n")
    lines.append("```json")
    lines.append(json.dumps(output_data, ensure_ascii=False, indent=2))
    lines.append("```\n")
    
    # 如果是某些特定角色，提取关键信息显示
    if role_name == "editor" and isinstance(output_data, dict):
        lines.append("### 评审结果\n")
        if "decision" in output_data:
            lines.append(f"**决策**: {output_data['decision']}\n")
        if "suggestions" in output_data:
            lines.append("**建议**:\n")
            for i, suggestion in enumerate(output_data.get("suggestions", []), 1):
                lines.append(f"{i}. {suggestion}")
            lines.append("")
    
    elif role_name == "character_designer" and "characters" in output_data:
        lines.append("### 人物列表\n")
        for char in output_data.get("characters", []):
            name = char.get("name", "未命名")
            role = char.get("role", "")
            lines.append(f"- **{name}** ({role})")
        lines.append("")
    
    return "\n".join(lines)

